#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include "MQTTClient.h"
#include <sys/msg.h>
#include "cJSON.h"

#define ADDRESS "mqtt.yyzlab.com.cn" 
#define CLIENTID "yuan1"
#define TOPIC_send "Device2AIOTSIM"
#define TOPIC_recv "AIOTSIM2Device"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L
#define MAX_TEXT 512//队列文本大小
#define MSG_KEY 9999//队列密钥
#define SHM_KEY 1234//内存共享密钥
#define SEM_KEY 5678//内存信号锁密钥
#define SHM_SIZE 512//共享内存文本大小

struct shmseg {
    int written;
    int read_flags[2];
    char text[SHM_SIZE];
};//内存文本结构体

struct msgbuf {
    long mtype;
    char mtext[512];
};//队列文本结构体

volatile MQTTClient_deliveryToken deliveredtoken;
pthread_mutex_t client_mutex = PTHREAD_MUTEX_INITIALIZER;//连接用的锁
pthread_mutex_t global_send_mutex = PTHREAD_MUTEX_INITIALIZER;//数据交互用的锁内存到mq
pthread_mutex_t global_recv_mutex = PTHREAD_MUTEX_INITIALIZER;//数据交互用的锁mq到队列
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int running = 1;
int mode=1;//mode=1是循环，mode=2是对比，mode=3是刷新
char global_send_buffer[512] = {0};//内存到mq
char global_recv_buffer[512] = {0};//mq到队列
char ceshi[512] = {0};
char global_mode2_buffer[512] = {0};//mode2的中转
int command=0;//刷新命令

//// 信号量操作：P操作（等待）内存
void sem_wait(int semid) {
    struct sembuf sb = {0, -1, 0};
    semop(semid, &sb, 1);
}


//// 信号量操作：V操作（释放）内存
void sem_signal(int semid) {
    struct sembuf sb = {0, 1, 0};
    semop(semid, &sb, 1);
}

void delivered(void *context, MQTTClient_deliveryToken dt) // 回调函数查看消息是否被服务器接收到
{
    //printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int i;
    char *payloadptr;
    

    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("   message: ");

    payloadptr = message->payload;
    for (i = 0; i < message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');
    //
    // 拷贝 payload 为 null 结尾的字符串
            char *json_str = malloc(message->payloadlen + 1);
            memcpy(json_str, message->payload, message->payloadlen);
            json_str[message->payloadlen] = '\0';

            cJSON *root = cJSON_Parse(json_str);
            free(json_str);

            if (!root) {
                printf("JSON Parse Error!\n");
                MQTTClient_free(topicName);
                MQTTClient_freeMessage(&message);
                
            }

             // 提取字段
            cJSON *lamp = cJSON_GetObjectItem(root, "lamp");
            cJSON *fan = cJSON_GetObjectItem(root, "fan");
            cJSON *alarm = cJSON_GetObjectItem(root, "alarm");
            cJSON *root1 = cJSON_CreateObject();

                   
                    // 3. 检查是否为布尔类型
    
        if (lamp && lamp->type == cJSON_True) {
            printf("lamp: true\n");
            cJSON_AddStringToObject(root1,"LED","on");
        } else {
            printf("lamp: false\n");
            cJSON_AddStringToObject(root1,"LED","off");
        }
    
    
        if (fan&&fan->type == cJSON_True) {
            printf("fan: true\n");
            cJSON_AddStringToObject(root1,"FAN","on");
        } else {
            printf("fan: false\n");
            cJSON_AddStringToObject(root1,"FAN","off");
        }
    
    
        if (alarm&&alarm->type == cJSON_True) {
            printf("alarm: true\n");
            cJSON_AddStringToObject(root1,"VOICE","on");
        } else {
            printf("alarm: false\n");
            cJSON_AddStringToObject(root1,"VOICE","off");
        }
             
                
                char *new_json = cJSON_Print(root1);
                printf("新 JSON: %s\n", new_json);

                // 可以发送 new_json 到共享内存或网络
                pthread_mutex_lock(&global_recv_mutex);
                //strncpy(global_recv_buffer,new_json,512);
                memset(global_recv_buffer, 0, sizeof(global_recv_buffer));
                strncpy(global_recv_buffer, new_json, SHM_SIZE - 1);
                global_recv_buffer[SHM_SIZE - 1] = '\0';
                //strncpy(local_buf, shm->text, SHM_SIZE - 1);
                //local_buf[SHM_SIZE - 1] = '\0';

                pthread_mutex_unlock(&global_recv_mutex);
                free(new_json);
                cJSON_Delete(root1);
            
           

            cJSON_Delete(root);



    //
    
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
} // 回调函数处理接收到的数据

void connlost(void *context, char *cause)
{
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}